#ifndef MULTINWORKQUERY_H
#define MULTINWORKQUERY_H
#include <QThread>
#include <tools/Gadget.h>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include "tools/Wings.h"

typedef unsigned int DLFLAG;
typedef unsigned int PSTRUCT;

#define  REGISTER_BASEINFO_163MSC_ADDRESS  QString("https://music.163.com/api/search/get/web?s=%1&type=1&offset=0&total=true&limit=%2")
#define  REGISTER_INFODOWN_163MSC_ADDRESS  QString("http://music.163.com/song/media/outer/url?id=%1.mp3")
#define  REGISTER_INFODETAIL_163MSC_ADDRESS  QString("http://music.163.com/api/song/detail/?id=%1&ids=[%1]")
#define  REGISTER_BASEINFO_163MSCLYC_ADDRESS  QString("http://music.163.com/api/song/lyric?id=%1&lv=1&kv=1&tv=-1")


#define FLAG_RESHOURCE_GET (1994031701)
#define FLAG_RESHOURCE_POST (1994031702)
#define FLAG_RESHOURCE_PUT (1994031703)
#define FLAG_VISIBLE_PROGRASS (1994031704)
#define FLAG_RESHOURCE_GETE (1994031705)
#define FLAG_RESHOURCE_POSTE (1994031706)
#define FLAG_RESHOURCE_PUTE (1994031707)

#define STRUCTYPE_MDRS (1994031100)
#define STRUCTYPE_LYRIC (1994031101)

#define DOWN_PROCESS (1994031791)
#define DOWN_PROCESSSTAT (1994031792)

#define SCROPED_RESDOWN_SINGEXEC(url, urlincast, multiarg, flag, lockey, receive, controlr){\
    QScopedPointer<ResdownLoad> T(new ResdownLoad((controlr)));\
    T->appendInfo(url, urlincast, multiarg, flag, lockey);\
    T->start(lockey);\
    T->captrueData(lockey, (receive));\
};

#define SCROPED_RESDOWN_ROPEEXEC(urls, urlincast, multiargs, flag, lockey, receive, controlr){\
    QScopedPointer<ResdownLoad> T(new ResdownLoad((controlr)));\
    T->appendInfo(urls, urlincast, multiargs, flag, lockey);\
    T->start(lockey);\
    T->captrueData(lockey, (receive));\
};

#define SCROPED_RESDOWN_SPLITEXEC(urls, urlincast, multiargs, flag, lockey, receive, controlr){\
    QScopedPointer<ResdownLoad> T(new ResdownLoad((controlr)));\
    for(int index=0;index < urls.size();index++)\
    {\
        T->appendInfo(urls[index], urlincast, multiargs[index], flag, lockey);\
        T->start(lockey);\
    }\
    T->captrueData(lockey, (receive));\
};

class ResdownLoad : public QObject{

    Q_OBJECT

public:
    ResdownLoad(QMap<ThreadPoint, NT::THREAD_STATE> &_impact_thread_);

    struct mdpldata{
      QList<QString> MDRS_ID;
      QList<QString> MDRS_NAME;
      QList<QString> MDRS_ARTIST;
      QList<QString> MDRS_COVER;
      QList<QString> MDRS_URL;
      QList<QString> MDRS_PIXMAP;
      QList<QString> MDRS_ALBUM;
      QList<QString> get(uint index){
            QString ID;
            QString NAME;
            QString ARTIST;
            QString COVER;
            QString URL;
            QString PIXMAP;
            QString ALBUM;
            index < (uint)MDRS_ID.size() ? ID = MDRS_ID[index] : ID = "";
            index < (uint)MDRS_NAME.size() ? NAME = MDRS_NAME[index] : NAME = "";
            index < (uint)MDRS_ARTIST.size() ? ARTIST = MDRS_ARTIST[index] : ARTIST = "";
            index < (uint)MDRS_COVER.size() ? COVER = MDRS_COVER[index] : COVER = "";
            index < (uint)MDRS_URL.size() ? URL = MDRS_URL[index] : URL = "";
            index < (uint)MDRS_PIXMAP.size() ? PIXMAP = MDRS_PIXMAP[index] : PIXMAP = "";
            index < (uint)MDRS_ALBUM.size() ? ALBUM = MDRS_ALBUM[index] : ALBUM = "";
            return {ID, NAME, ARTIST, COVER, URL, PIXMAP, ALBUM};
        }
    };

    QList<DLFLAG> GETFLAG = {FLAG_RESHOURCE_GET, FLAG_RESHOURCE_GETE};
    QList<DLFLAG> POSTFLAG = {FLAG_RESHOURCE_POST, FLAG_RESHOURCE_POSTE};
    QList<DLFLAG> PUTFLAG = {FLAG_RESHOURCE_PUT, FLAG_RESHOURCE_PUTE};
    QList<DLFLAG> VARIANTFLAG = {FLAG_RESHOURCE_GETE, FLAG_RESHOURCE_POSTE, FLAG_RESHOURCE_PUTE};

    template<typename _addre, typename _addreqry, typename _multi, typename flag_MCR>
    void appendInfo(_addre url, _addreqry urlincast, _multi multiarg, flag_MCR flag, QString lockey=""){
        QList<QVariant> urls; QList<QVariant> incast; QList<QVariant> multiargs; QList<QVariant> flags;
        urls.append(url);
        incast.append(urlincast);
        multiargs.append(multiarg);
        flags.append(flag);
        infomap[lockey]["address"].append(urls);
        infomap[lockey]["address-incast"].append(incast);
        infomap[lockey]["multiargs"].append(multiargs);
        infomap[lockey]["downFlags"].append(flags);
    }

    QMap<QString, QString> getrawHeader(QString url);

    void start(QString lockey="");

    QList<QVariant> captrueData(QString lockey="");

    void captrueData(QString lockey, QList<QVariant> &data);

    void captrueData(QString lockey, QVariant &data);

    static QJsonDocument jsparser(QByteArray data);

    static mdpldata jsparserTostruct(QJsonDocument jsondata, PSTRUCT resourceType){
        mdpldata sctructdata;
        if (resourceType == STRUCTYPE_MDRS)
        {
            QJsonArray jsarry;
            if (!jsondata["result"].isNull() && jsondata["result"].type() == QJsonValue::Object)
            {
                if (!jsondata["result"]["songs"].isNull() && jsondata["result"]["songs"].type() == QJsonValue::Array)
                {
                    jsarry = jsondata["result"]["songs"].toArray();

                }
            }
            for(int index = 0; index < jsarry.size(); index++)
            {
                QJsonValue data = jsarry[index];
                if (data.isObject())
                {
                    QJsonObject singSongs = data.toObject();
                    QString ID = QString::number(singSongs["id"].toInt());
                    QString NAME = singSongs["name"].toString();
                    sctructdata.MDRS_ID.append(ID);
                    sctructdata.MDRS_NAME.append(NAME);
                    QJsonArray arrayArtist = singSongs["artists"].toArray();
                    if (arrayArtist.size() > 0)
                    {
                        QJsonObject singArtist = arrayArtist[0].toObject();
                        sctructdata.MDRS_ARTIST.append(singArtist["name"].toString());
                        sctructdata.MDRS_COVER.append(singArtist["img1v1Url"].toString());
                    }
                    QString id = QString::number(singSongs["id"].toInt());
                    sctructdata.MDRS_URL.append(REGISTER_INFODOWN_163MSC_ADDRESS.arg(id));
                } else continue;
            }
        }
        else if (resourceType == STRUCTYPE_LYRIC)
        {
            QJsonArray jsarry;
            if (!jsondata["result"].isNull() && jsondata["result"].type() == QJsonValue::Object)
            {
                if (!jsondata["result"]["songs"].isNull() && jsondata["result"]["songs"].type() == QJsonValue::Array)
                {
                    jsarry = jsondata["result"]["songs"].toArray();

                }
            }
            for(int index = 0; index < jsarry.size(); index++)
            {
                QJsonValue data = jsarry[index];
                if (data.isObject())
                {
                    QJsonObject singSongs = data.toObject();
                    QString ID = QString::number(singSongs["id"].toInt());
                    QString NAME = singSongs["name"].toString();
                    sctructdata.MDRS_ID.append(ID);
                    sctructdata.MDRS_NAME.append(NAME);
                    QJsonArray arrayArtist = singSongs["artists"].toArray();
                    if (arrayArtist.size() > 0)
                    {
                        QJsonObject singArtist = arrayArtist[0].toObject();
                        sctructdata.MDRS_ARTIST.append(singArtist["name"].toString());
                        sctructdata.MDRS_COVER.append(singArtist["img1v1Url"].toString());
                    }
                    QString id = QString::number(singSongs["id"].toInt());
                    sctructdata.MDRS_URL.append(REGISTER_INFODOWN_163MSC_ADDRESS.arg(id));
                } else continue;
            }
        }
        return sctructdata;
    }

    static void g_jsonkey(QStringList primary_key, QString secondary_key, QList<QString> &receive, QJsonDocument jsondata){
        QJsonObject object = jsondata.object();
        if (object.isEmpty())
        {
            QJsonArray array = jsondata.array();
            for(int index = 0; index < array.size(); index++)
            {
                if (array[index].type() == QJsonValue::Object)
                {
                    g_jsonkey(primary_key, secondary_key, receive, QJsonDocument(array[index].toObject()));
                }
            }
        }
        else
        {
            QString idnum;
            foreach(QString k, object.keys())
            {
                QJsonValue value = object[k];
                if (k == "id" && value.isDouble()) idnum = QString::number(value.toInt());
                if (k == secondary_key && value.type() == QJsonValue::String)
                {
                    if (!idnum.isEmpty())
                    {
                        receive.append(idnum + "-" + value.toString());
                        idnum.clear();
                    }
                    else
                    {
                        QString i = value.toString();
                        if (!i.isEmpty()) receive.append(value.toString());
                    }
                }
                else if (value.type() == QJsonValue::Object)
                {
                    if (k == primary_key[0])
                    {
                        primary_key.removeAt(0);
                        g_jsonkey(primary_key, secondary_key, receive, QJsonDocument(value.toObject()));
                    }
                }
                else if (value.type() == QJsonValue::Array)
                {
                    g_jsonkey(primary_key, secondary_key, receive, QJsonDocument( value.toArray()));
                }
            }
        }
        receive.removeDuplicates();
    }


    static void parserIncast(QUrlQuery &g, QVariant data);

private:
    Nlwingsing wingsing;
    QNetworkRequest request;
    bool runningState;
    QString runningKey;

    QMap<QString, QMap<QString, QList<QVariant>>> infomap;
    QMap<QString, bool> infomapState;
    QMap<ThreadPoint, NT::THREAD_STATE> *impact_thread;

    void run();


signals:
    void request_process(qint64 current, qint64 total);
    void request_process_exdwings(bool stat);
    void finished();
};
#endif // MULTINWORKQUERY_H
